package com.legrand.www.module.common.util;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author xiah
 * @description 手机号和身份证验证
 */

public class PhoneAndIDcardCheckUtil {

    private static final String TELEPHONE = "^(13[0-9]|14[0-9]|15[0-9]|18[0-9]|17[0-9])\\d{8}$";
    // "^0?(13[0-9]|15[012356789]|17[013678]|18[0-9]|14[57])[0-9]{8}$";

    private static final Pattern PATTERN_TEL = Pattern.compile(TELEPHONE);

    /**
     * 城市代码
     */
    private static final List<String> CITY_CODE = Arrays.asList("11", "12", "13", "14", "15", "21", "22", "23",
            "31", "32", "33", "34",
            "35", "36", "37", "41", "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63",
            "64", "65", "71",
            "81", "82", "91");

    /**
     * 加权因子
     */
    private static final int[] POWER = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    public static boolean isTelephone(String mobilephone) {
        if (isEmpty(mobilephone)) {
            return false;
        }
        Matcher matcher = PATTERN_TEL.matcher(mobilephone);
        return matcher.matches();
    }

    public static boolean isTelephones(List<String> noList) {
        if (noList == null || noList.isEmpty()) {
            return false;
        }
        for (String phone : noList) {
            if (!isTelephone(phone)) {
                return false;
            }
        }
        return true;
    }

    public static boolean ValidatedDcard(String idcard) {
        if (idcard.length() == 15) {
            return validate15IDCard(idcard);
        }
        return validate18Idcard(idcard);
    }

    private static boolean validate18Idcard(String idcard) {
        if (!validateProvinceAndBirthday(idcard)) {
            return false;
        }
        String idcard17 = idcard.substring(0, 17);
        if (!isDigital(idcard17)) {
            return false;
        }
        String idcard18Code = idcard.substring(17, 18);
        char c[] = idcard17.toCharArray();
        int bit[] = converCharToInt(c);
        int sum17 = 0;
        sum17 = getPowerSum(bit);
        // 将和值与11取模得到余数进行校验码判断
        String checkCode = getCheckCodeBySum(sum17);
        if (null == checkCode) {
            return false;
        }
        // 将身份证的第18位与算出来的校码进行匹配，不相等就为假
        return idcard18Code.equalsIgnoreCase(checkCode);
    }

    private static int getPowerSum(int[] bit) {
        int sum = 0;

        if (POWER.length != bit.length) {
            return sum;
        }

        for (int i = 0; i < bit.length; i++) {
            for (int j = 0; j < POWER.length; j++) {
                if (i == j) {
                    sum = sum + bit[i] * POWER[j];
                }
            }
        }
        return sum;
    }

    private static boolean validateProvinceAndBirthday(String idcard) {
        if (isEmpty(idcard) || (idcard.length() != 15 && idcard.length() != 18)) {
            return false;
        }
        String provinceId = idcard.substring(0, 2);
        // 校验省份
        if (!CITY_CODE.contains(provinceId)) {
            return false;
        }
        String birthday = null;
        if (idcard.length() == 15) {
            if (!isDigital(idcard)) {
                return false;
            }
            birthday = idcard.substring(6, 12);
        } else {
            if (!isDigital(idcard.substring(0, 17))) {
                return false;
            }
            birthday = idcard.substring(6, 14);
        }
        SimpleDateFormat sdf = idcard.length() == 18 ? new SimpleDateFormat("yyyyMMdd") : new SimpleDateFormat
                ("yyMMdd");
        try {
            Date birthDate = sdf.parse(birthday);
            String tmpDate = sdf.format(birthDate);
            if (!tmpDate.equals(birthday)) {// 身份证日期错误
                return false;
            }
        } catch (ParseException e1) {

            return false;
        }

        return true;

    }

    private static boolean validate15IDCard(String idcard) {
        return validateProvinceAndBirthday(idcard);
    }

    private static boolean isDigital(String str) {
        return str.matches("^[0-9]*$");
    }

    private static int[] converCharToInt(char[] c) throws NumberFormatException {
        int[] a = new int[c.length];
        int k = 0;
        for (char temp : c) {
            a[k++] = Integer.parseInt(String.valueOf(temp));
        }
        return a;
    }

    private static String getCheckCodeBySum(int sum17) {
        String checkCode = null;
        switch (sum17 % 11) {
            case 10:
                checkCode = "2";
                break;
            case 9:
                checkCode = "3";
                break;
            case 8:
                checkCode = "4";
                break;
            case 7:
                checkCode = "5";
                break;
            case 6:
                checkCode = "6";
                break;
            case 5:
                checkCode = "7";
                break;
            case 4:
                checkCode = "8";
                break;
            case 3:
                checkCode = "9";
                break;
            case 2:
                checkCode = "x";
                break;
            case 1:
                checkCode = "0";
                break;
            case 0:
                checkCode = "1";
                break;
        }
        return checkCode;
    }

    private static boolean isEmpty(String s) {
        return s == null || s.length() <= 0;
    }
}
